#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>

#include "List.h"

List* listConstruct(Element* first)
{
	List *list;
	list = (List*) malloc(sizeof(List));
	list->firstElement = first;
	list->currentElement = NULL;
	list->count = 1;
	return list;
}

void listDeconstruct(List *list)
{
	Element *next = list->firstElement;
	Element *original = list->firstElement;

	while (next != NULL)
	{
		next = original->next;
		elementDeconstruct(original);
		original = next;
	}

	free(list);
}

void listAddElement(List *list, Element* newElement)
{
	Element *element = list->firstElement;
	if(list->firstElement == NULL)
		list->firstElement = newElement;
	else
	{
		while(element->next != NULL)
			element = element->next;

		element->next = newElement;
	}
	
	list->count++;
}

void listAddElementToFront(List *list, Element* newElement)
{
	newElement->next = list->firstElement;
	list->firstElement = newElement;
	list->count++;
}

void listDeleteElement(List *list, Element* element)
{
	if (list->firstElement == element) 
	{
		Element *first = list->firstElement;
		if (list->firstElement->next != NULL)
			list->firstElement = list->firstElement->next;
		else 
			list->firstElement = NULL;
		
		elementDeconstruct(first);
	}
	else if (list->firstElement->next != NULL)
	{
		Element *previous = list->firstElement;
		Element *current = list->firstElement->next;

		if(current->next == NULL)
		{
			previous->next = NULL;
			elementDeconstruct(current);
		}
		else
		{
			Element *itemThatIsDeleted;
			while (current->next != NULL)
			{
				if(current == element)
				{
					previous->next = current->next;
					itemThatIsDeleted = current;
				}

				previous = current;
				current = current ->next;
			}

			//It was the last item in the list
			if(current == element)
			{
				previous->next = NULL;
				itemThatIsDeleted = current;
			}

			elementDeconstruct(itemThatIsDeleted);
		}
	}

	list->count--;
}

List* listCopy(List *list)
{
	Element *itemInCopyList;
	Element *item = list->firstElement;
	List *copyList = (List*) malloc(sizeof(copyList));
	
	copyList->firstElement = elementConstruct(list->firstElement->value);
	itemInCopyList = copyList->firstElement;

	while (item->next != NULL)
	{
		Element *newItem = elementConstruct(item->next->value);
		itemInCopyList->next = newItem;
		itemInCopyList = itemInCopyList->next;
		item = item->next;
	}

	return copyList;
}

void listPrepareForLooping(List *list)
{
	if (list == NULL || list->firstElement == NULL)
		return;

	list->currentElement = list->firstElement;
}

Element* listNextElement(List *list)
{
	Element *next = list->currentElement;

	if(list->currentElement != NULL)
		list->currentElement = list->currentElement->next;
	else
		next = NULL;

	return next;
}

Element* listElementAtIndex(List *list, int index)
{
	Element *element;
	listPrepareForLooping(list);
	element = listNextElement(list);
	int i = 0;

	while (i != index)
	{
		element = listNextElement(list);
		i++;
	}

	return element;
}

/**************************************************************
Element Methods
**************************************************************/
Element* elementConstruct(void* value)
{
	Element *element;
	element = (Element*) malloc(sizeof(Element));
	element->value = value;
	element->next = NULL;
	return element;
}

void elementDeconstruct(Element* element)
{
	free(element->value);
	free(element);
}